//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_issue_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/issue_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_issue_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectIssueApiImpl) ListVote(ctx context.Context, req *project_issue_api.ListVoteRequest) (*project_issue_api.ListVoteResponse, error) {
	emptyList := []*project_issue_api.VoteInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_issue_api.ListVoteResponse{
			Code:     project_issue_api.ListVoteResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			VoteList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_issue_api.ListVoteResponse{
			Code:     project_issue_api.ListVoteResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			VoteList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_issue_api.ListVoteResponse{
			Code:     project_issue_api.ListVoteResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			VoteList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := issue_dao.IssueDao.Exist(ctx, req.ProjectId, req.IssueId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_issue_api.ListVoteResponse{
			Code:     project_issue_api.ListVoteResponse_CODE_NO_ISSUE,
			ErrMsg:   "工单不存在",
			VoteList: emptyList,
		}, nil
	}

	voteItemList, err := issue_dao.VoteDao.List(ctx, req.IssueId)
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, voteItem := range voteItemList {
		userIdList = append(userIdList, voteItem.VoteUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	voteList := []*project_issue_api.VoteInfo{}
	for _, voteItem := range voteItemList {
		vote := voteItem.ToVoteInfo()
		userItem, ok := userItemMap[voteItem.VoteUserId]
		if ok {
			vote.VoteDisplayName = userItem.BasicInfo.DisplayName
			vote.VoteLogoUri = userItem.BasicInfo.LogoUri
		}
		voteList = append(voteList, vote)
	}
	return &project_issue_api.ListVoteResponse{
		Code:     project_issue_api.ListVoteResponse_CODE_OK,
		VoteList: voteList,
	}, nil
}

func (apiImpl *ProjectIssueApiImpl) SetVote(ctx context.Context, req *project_issue_api.SetVoteRequest) (*project_issue_api.SetVoteResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_issue_api.SetVoteResponse{
			Code:   project_issue_api.SetVoteResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_issue_api.SetVoteResponse{
			Code:   project_issue_api.SetVoteResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_issue_api.SetVoteResponse{
			Code:   project_issue_api.SetVoteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_issue_api.SetVoteResponse{
			Code:   project_issue_api.SetVoteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := issue_dao.IssueDao.Exist(ctx, req.ProjectId, req.IssueId)
	if err != nil {
		return nil, err
	}

	if !exist {
		return &project_issue_api.SetVoteResponse{
			Code:   project_issue_api.SetVoteResponse_CODE_NO_ISSUE,
			ErrMsg: "工单不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = issue_dao.VoteDao.Upsert(sessCtx, &issue_dao.VoteInfoDbItem{
			IssueId: req.IssueId,
			BasicInfo: issue_dao.BasicVoteInfoDbItem{
				EstimateMinutes: req.Vote.EstimateMinutes,
				Important:       req.Vote.Important,
				Urgency:         req.Vote.Urgency,
				ExtraDesc:       req.Vote.ExtraDesc,
			},
			TimeStamp:  nowTime,
			VoteUserId: sessionItem.UserId,
		})
		if err != nil {
			return nil, err
		}
		return &project_issue_api.SetVoteResponse{
			Code: project_issue_api.SetVoteResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*project_issue_api.SetVoteResponse), nil
}

func (apiImpl *ProjectIssueApiImpl) RemoveVote(ctx context.Context, req *project_issue_api.RemoveVoteRequest) (*project_issue_api.RemoveVoteResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_issue_api.RemoveVoteResponse{
			Code:   project_issue_api.RemoveVoteResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_issue_api.RemoveVoteResponse{
			Code:   project_issue_api.RemoveVoteResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_issue_api.RemoveVoteResponse{
			Code:   project_issue_api.RemoveVoteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_issue_api.RemoveVoteResponse{
			Code:   project_issue_api.RemoveVoteResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := issue_dao.IssueDao.Exist(ctx, req.ProjectId, req.IssueId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_issue_api.RemoveVoteResponse{
			Code:   project_issue_api.RemoveVoteResponse_CODE_NO_ISSUE,
			ErrMsg: "工单不存在",
		}, nil
	}

	exist, err = issue_dao.VoteDao.Exist(ctx, req.IssueId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_issue_api.RemoveVoteResponse{
			Code: project_issue_api.RemoveVoteResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = issue_dao.VoteDao.Remove(sessCtx, req.IssueId, sessionItem.UserId)
		if err != nil {
			return nil, err
		}
		return &project_issue_api.RemoveVoteResponse{
			Code: project_issue_api.RemoveVoteResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*project_issue_api.RemoveVoteResponse), nil
}
